<template>
  <div class="ttt-loading" :style="loadingStyle">
    <div class="ttt-loading-center">
      <ul class="ttt-loading-rainbow" v-if="loadingType === 'rainbow'">
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
      </ul>
      <ul class="ttt-loading-wave" v-else-if="loadingType === 'wave'">
        <li></li>
        <li></li>
      </ul>
      <div class="ttt-loading-text" v-if="text && text !== ''">{{ text }}</div>
    </div>
  </div>
</template>

<script lang="ts">
import { computed, defineComponent } from 'vue'
import type { PropType, CSSProperties } from 'vue'

export type LoadingType = 'wave' | 'rainbow'

export interface LoadingProps {
  text: string
  bgColor: string
  textColor: string
  loadingType: LoadingType
}

export default defineComponent({
  name: 'tttLoading',
  props: {
    text: {
      type: String as PropType<string>,
      default: null
    },
    bgColor: {
      type: String as PropType<string>,
      default: 'rgba(0, 0, 0, .8)'
    },
    textColor: {
      type: String as PropType<string>,
      default: '#fff'
    },
    loadingType: {
      type: String as PropType<LoadingType>,
      default: 'wave'
    }
  },
  setup(props: LoadingProps) {
    const loadingStyle = computed<CSSProperties>((): CSSProperties => {
      return {
        backgroundColor: props.bgColor,
        color: props.textColor
      }
    })

    return {
      loadingStyle
    }
  }
})
</script>

<style scoped lang="scss">
@keyframes ttt-loading-animation-spin {
  from {
    transform: rotate(0);
  }
  to {
    transform: rotate(360deg);
  }
}

@keyframes ttt-loading-animation-wave {
  0% {
    transform: scale(0);
    opacity: 1;
  }
  50% {
    opacity: 1;
  }
  100% {
    transform: scale(1);
    opacity: 0;
  }
}

.ttt-loading {
  width: 100%;
  height: 100%;
  position: relative;
  overflow: hidden;

  > .ttt-loading-center {
    position: absolute;
    left: 50%;
    top: 50%;
    transform-origin: center center;
    transform: translateX(-50%) translateY(-50%);

    > .ttt-loading-wave {
      width: 100%;
      min-width: 60rem;
      height: 60rem;
      position: relative;

      > li {
        width: 50rem;
        height: 50rem;
        position: absolute;
        left: 0;
        top: 0;
        right: 0;
        bottom: 0;
        margin: auto;
        box-sizing: border-box;
        border-radius: 50%;
        border: 2rem solid #47ebeb;
        animation: ttt-loading-animation-wave 1.5s infinite ease;
        transform: scale(0);

        @for $i from 0 through 4 {
          &:nth-of-type(#{$i + 1}) {
            animation-delay: 600ms * $i;
          }
        }
      }
    }

    > .ttt-loading-rainbow {
      width: 100%;
      min-width: 60rem;
      height: 60rem;
      position: relative;
      transform: rotate(-45deg);

      > li {
        position: absolute;
        left: 0;
        top: 0;
        right: 0;
        bottom: 0;
        margin: auto;
        border-radius: 50%;
        border: 2rem solid transparent;
        animation: ttt-loading-animation-spin 1.5s cubic-bezier(0.175, 0.885, 0.32, 1.275) infinite;

        @for $i from 1 through 5 {
          &:nth-of-type(#{$i}) {
            width: 10rem * $i;
            height: 10rem * $i;
            animation-delay: -100ms * $i;
            @if $i==5 {
              border-top-color: #eb4747;
              border-right-color: #eb4747;
            }
            @if $i==4 {
              border-top-color: #ebeb47;
              border-right-color: #ebeb47;
            }
            @if $i==3 {
              border-top-color: #47eb47;
              border-right-color: #47eb47;
            }
            @if $i==2 {
              border-top-color: #47ebeb;
              border-right-color: #47ebeb;
            }
            @if $i==1 {
              border-top-color: #4747eb;
              border-right-color: #4747eb;
            }
          }
        }
      }
    }

    > .ttt-loading-text {
      height: 24rem;
      line-height: 24rem;
      white-space: nowrap;
      text-align: center;
    }
  }
}
</style>
